From 40dd9a21b281661a0966e877e4c5386cf30843f5 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Fri, 27 Feb 2026 19:24:30 -0500 Subject: [PATCH 1/3] fix: Signal Desktop v8.0.0 binary ACI compatibility Signal Desktop v8.0.0 switched from string ACI fields to binary ACI encoding in protobuf messages. This breaks reactions, mentions, quotes, and other message features when the library cannot parse the new format. Two-part fix applied via patch to signal-cli v0.13.24 source build: 1. Bump signal-service-java from unofficial_137 to unofficial_138, which adds dual-format ACI parsing (string + binary fallback via ServiceId.parseOrNull). 2. Add defensive null guards in MessageEnvelope.java for cases where ServiceId resolution still fails (e.g. ACI.UNKNOWN). Preserves message content with UNKNOWN_UUID fallback rather than dropping entire message components (quotes, reactions, mentions, etc.). The patch is applied during the x86_64 source build. The source-built installDist output replaces the release tarball, so both the JVM and native (GraalVM) paths get the fix. Non-x86_64 architectures continue using the unpatched release tarball until signal-cli cuts a new release with unofficial_138. See: https://github.com/AsamK/signal-cli/pull/1944 Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 41 ++++++++++----- ext/patches/fix-binary-aci.patch | 89 ++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 ext/patches/fix-binary-aci.patch diff --git a/Dockerfile b/Dockerfile index 96e845b2..1aa371a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,7 @@ ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries COPY ext/libraries/libsignal-client/signal-cli-native.patch /tmp/signal-cli-native.patch +COPY ext/patches/fix-binary-aci.patch /tmp/fix-binary-aci.patch # use architecture specific libsignal_jni.so RUN arch="$(uname -m)"; \ @@ -75,6 +76,7 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \ && git clone https://github.com/AsamK/signal-cli.git signal-cli-${SIGNAL_CLI_VERSION}-source \ && cd signal-cli-${SIGNAL_CLI_VERSION}-source \ && git checkout -q v${SIGNAL_CLI_VERSION} \ + && git apply /tmp/fix-binary-aci.patch \ && cd /tmp && mkdir -p /tmp/graalvm && tar xf gvm.tar.gz -C /tmp/graalvm --strip-components=1 \ && export GRAALVM_HOME=/tmp/graalvm \ && export PATH=/tmp/graalvm/bin:$PATH \ @@ -82,10 +84,14 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \ && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' src/main/java/org/asamk/signal/BaseConfig.java \ && ./gradlew build \ && ./gradlew installDist \ - && ls build/install/signal-cli/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found. Maybe the version needs to be bumped in the signal-cli-rest-api Dockerfile?\n\n" && echo "Available version: \n" && ls build/install/signal-cli/lib/libsignal-client-* && echo "\n\n" && exit 1) \ + && BUILT_LIBSIGNAL_JAR=$(ls build/install/signal-cli/lib/libsignal-client-*.jar | head -1) \ + && echo "Built libsignal-client jar: ${BUILT_LIBSIGNAL_JAR}" \ + && rm -rf /tmp/signal-cli-${SIGNAL_CLI_VERSION} \ + && cp -a build/install/signal-cli /tmp/signal-cli-${SIGNAL_CLI_VERSION} \ && cd /tmp \ - && cp signal-cli-${SIGNAL_CLI_VERSION}-source/build/install/signal-cli/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal-client.jar \ + && cp "${BUILT_LIBSIGNAL_JAR}" libsignal-client.jar \ && zip -qu libsignal-client.jar libsignal_jni.so \ + && cp libsignal-client.jar /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/$(basename "${BUILT_LIBSIGNAL_JAR}") \ && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \ && git apply /tmp/signal-cli-native.patch \ && ./gradlew -q nativeCompile; \ @@ -113,20 +119,27 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \ echo "Unknown architecture"; \ fi; -# replace libsignal-client - -RUN ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found. Maybe the version needs to be bumped in the signal-cli-rest-api Dockerfile?\n\n" && echo "Available version: \n" && ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-* && echo "\n\n" && exit 1) - -# workaround until upstream is fixed -RUN cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib \ - && unzip signal-cli-${SIGNAL_CLI_VERSION}.jar \ - && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' org/asamk/signal/BaseConfig.class \ - && zip -r signal-cli-${SIGNAL_CLI_VERSION}.jar org/ META-INF/ \ - && rm -rf META-INF \ - && rm -rf org +# Post-processing: inject native libsignal_jni.so and apply BaseConfig workaround. +# On x86_64 the source build (above) already produced a patched installDist with +# the native lib injected, so we only need to package it. On other architectures +# the release tarball is still unpatched — apply the BaseConfig sed workaround and +# inject the native lib there. + +RUN if [ "$(uname -m)" != "x86_64" ]; then \ + ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar \ + || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found.\n\n" \ + && ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-* && exit 1) \ + && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib \ + && unzip signal-cli-${SIGNAL_CLI_VERSION}.jar \ + && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' org/asamk/signal/BaseConfig.class \ + && zip -r signal-cli-${SIGNAL_CLI_VERSION}.jar org/ META-INF/ \ + && rm -rf META-INF \ + && rm -rf org \ + && cd /tmp/ \ + && zip -qu /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal_jni.so; \ + fi RUN cd /tmp/ \ - && zip -qu /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal_jni.so \ && zip -qr signal-cli-${SIGNAL_CLI_VERSION}.zip signal-cli-${SIGNAL_CLI_VERSION}/* \ && unzip -q /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip -d /opt \ && rm -f /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip diff --git a/ext/patches/fix-binary-aci.patch b/ext/patches/fix-binary-aci.patch new file mode 100644 index 00000000..62eac82c --- /dev/null +++ b/ext/patches/fix-binary-aci.patch @@ -0,0 +1,89 @@ +Fix Signal Desktop v8.0.0 binary ACI encoding compatibility. + +Signal Desktop v8.0.0 switched from string ACI fields to binary ACI encoding +in protobuf messages. This causes null ServiceId values when the library +cannot parse the new format, breaking reactions, mentions, quotes, and other +message features. + +Two-part fix: +1. Bump signal-service-java from unofficial_137 to unofficial_138 which adds + dual-format ACI parsing (string + binary fallback). +2. Add defensive null guards in MessageEnvelope.java for cases where ServiceId + resolution still fails (e.g. ACI.UNKNOWN), preserving message content with + UNKNOWN_UUID fallback rather than dropping entire message components. + +See: https://github.com/AsamK/signal-cli/pull/1944 + +diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml +index 9b1bd5f4..0000001 100644 +--- a/gradle/libs.versions.toml ++++ b/gradle/libs.versions.toml +@@ -11,7 +11,7 @@ slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } + slf4j-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" } + logback = "ch.qos.logback:logback-classic:1.5.25" + +-signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_137" ++signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_138" + sqlite = "org.xerial:sqlite-jdbc:3.51.1.0" + hikari = "com.zaxxer:HikariCP:7.0.2" + junit-jupiter-bom = { module = "org.junit:junit-bom", version.ref = "junit" } +diff --git a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java +index 37946057..57a5a0f4 100644 +--- a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java ++++ b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java +@@ -132,6 +132,7 @@ public record MessageEnvelope( + return new Data(dataMessage.getTimestamp(), + dataMessage.getGroupContext().map(GroupContext::from), + dataMessage.getStoryContext() ++ .filter(s -> s.getAuthorServiceId() != null) + .map((SignalServiceDataMessage.StoryContext storyContext) -> StoryContext.from(storyContext, + recipientResolver, + addressResolver)), +@@ -143,9 +144,10 @@ public record MessageEnvelope( + dataMessage.isEndSession(), + dataMessage.isProfileKeyUpdate(), + dataMessage.getProfileKey().isPresent(), +- dataMessage.getReaction().map(r -> Reaction.from(r, recipientResolver, addressResolver)), ++ dataMessage.getReaction() ++ .filter(r -> r.getTargetAuthor() != null) ++ .map(r -> Reaction.from(r, recipientResolver, addressResolver)), + dataMessage.getQuote() +- .filter(q -> q.getAuthor() != null && q.getAuthor().isValid()) + .map(q -> Quote.from(q, recipientResolver, addressResolver, fileProvider)), + dataMessage.getPayment().map(p -> p.getPaymentNotification().isPresent() ? Payment.from(p) : null), + dataMessage.getAttachments() +@@ -159,10 +161,15 @@ public record MessageEnvelope( + .toList()) + .orElse(List.of()), + dataMessage.getPollCreate().map(PollCreate::from), +- dataMessage.getPollVote().map(p -> PollVote.from(p, recipientResolver, addressResolver)), ++ dataMessage.getPollVote() ++ .filter(p -> p.getTargetAuthor() != null) ++ .map(p -> PollVote.from(p, recipientResolver, addressResolver)), + dataMessage.getPollTerminate().map(PollTerminate::from), + dataMessage.getMentions() +- .map(a -> a.stream().map(m -> Mention.from(m, recipientResolver, addressResolver)).toList()) ++ .map(a -> a.stream() ++ .filter(m -> m.getServiceId() != null) ++ .map(m -> Mention.from(m, recipientResolver, addressResolver)) ++ .toList()) + .orElse(List.of()), + dataMessage.getPreviews() + .map(a -> a.stream().map(preview -> Preview.from(preview, fileProvider)).toList()) +@@ -241,10 +248,13 @@ public record MessageEnvelope( + RecipientAddressResolver addressResolver, + final AttachmentFileProvider fileProvider + ) { ++ final var author = quote.getAuthor() != null && quote.getAuthor().isValid() ++ ? addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())) ++ .toApiRecipientAddress() ++ : new RecipientAddress(RecipientAddress.UNKNOWN_UUID); + return new Quote(quote.getId(), +- addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())) +- .toApiRecipientAddress(), +- Optional.of(quote.getText()), ++ author, ++ Optional.ofNullable(quote.getText()), + quote.getMentions() == null + ? List.of() + : quote.getMentions() From 7e1b98f0c2163bceaa159d89816b2b6c2d0cb2d1 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Fri, 27 Feb 2026 20:17:50 -0500 Subject: [PATCH 2/3] fix: use absolute path for libsignal-client jar copy The BUILT_LIBSIGNAL_JAR variable captured a relative path that became invalid after cd /tmp. Switch to capturing just the filename and using the already-copied absolute path. Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1aa371a1..96928ddf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -84,14 +84,14 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \ && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' src/main/java/org/asamk/signal/BaseConfig.java \ && ./gradlew build \ && ./gradlew installDist \ - && BUILT_LIBSIGNAL_JAR=$(ls build/install/signal-cli/lib/libsignal-client-*.jar | head -1) \ - && echo "Built libsignal-client jar: ${BUILT_LIBSIGNAL_JAR}" \ + && BUILT_LIBSIGNAL_JAR_NAME=$(ls build/install/signal-cli/lib/ | grep 'libsignal-client-.*\.jar' | head -1) \ + && echo "Built libsignal-client jar: ${BUILT_LIBSIGNAL_JAR_NAME}" \ && rm -rf /tmp/signal-cli-${SIGNAL_CLI_VERSION} \ && cp -a build/install/signal-cli /tmp/signal-cli-${SIGNAL_CLI_VERSION} \ && cd /tmp \ - && cp "${BUILT_LIBSIGNAL_JAR}" libsignal-client.jar \ + && cp /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/${BUILT_LIBSIGNAL_JAR_NAME} libsignal-client.jar \ && zip -qu libsignal-client.jar libsignal_jni.so \ - && cp libsignal-client.jar /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/$(basename "${BUILT_LIBSIGNAL_JAR}") \ + && cp libsignal-client.jar /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/${BUILT_LIBSIGNAL_JAR_NAME} \ && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \ && git apply /tmp/signal-cli-native.patch \ && ./gradlew -q nativeCompile; \ From 53b2d53dc45563d73f62903ecdb25137ce6a1ae1 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Tue, 10 Mar 2026 10:30:43 -0400 Subject: [PATCH 3/3] feat: upgrade to signal-cli v0.14.1 with Java 25 runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Download pre-built signal-cli release tarball instead of building from source - Extract platform-specific libsignal_jni.so from the release jar at build time (no more bundled .so binaries in the repo) - Switch runtime base to eclipse-temurin:25-jre-noble (Java 25 required) - Remove GraalVM native image build, source patches, and BaseConfig hacks - Fix netcat package name for noble (netcat-openbsd) - Fix ENV syntax (legacy format → equals sign) Resolves DeprecatedVersionException (StatusCode 499) from Signal servers that rejected the older signal-cli 0.14.0-SNAPSHOT client. Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 162 +++++++++-------------------------------------------- 1 file changed, 28 insertions(+), 134 deletions(-) diff --git a/Dockerfile b/Dockerfile index 96928ddf..afce7c3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,7 @@ -ARG SIGNAL_CLI_VERSION=0.13.24 -ARG LIBSIGNAL_CLIENT_VERSION=0.87.0 -ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION=0.13.24+morph027+2 +ARG SIGNAL_CLI_VERSION=0.14.1 +ARG LIBSIGNAL_CLIENT_VERSION=0.87.4 ARG SWAG_VERSION=1.16.4 -ARG GRAALVM_VERSION=21.0.0 -#ARG GRAALVM_VERSION=25.0.2 ARG BUILD_VERSION_ARG=unset @@ -13,29 +10,13 @@ FROM golang:1.24-bookworm AS buildcontainer ARG SIGNAL_CLI_VERSION ARG LIBSIGNAL_CLIENT_VERSION ARG SWAG_VERSION -ARG GRAALVM_VERSION ARG BUILD_VERSION_ARG -ARG SIGNAL_CLI_NATIVE_PACKAGE_VERSION - -COPY ext/libraries/libsignal-client/v${LIBSIGNAL_CLIENT_VERSION} /tmp/libsignal-client-libraries -COPY ext/libraries/libsignal-client/signal-cli-native.patch /tmp/signal-cli-native.patch -COPY ext/patches/fix-binary-aci.patch /tmp/fix-binary-aci.patch - -# use architecture specific libsignal_jni.so -RUN arch="$(uname -m)"; \ - case "$arch" in \ - aarch64) cp /tmp/libsignal-client-libraries/arm64/libsignal_jni.so /tmp/libsignal_jni.so ;; \ - armv7l) cp /tmp/libsignal-client-libraries/armv7/libsignal_jni.so /tmp/libsignal_jni.so ;; \ - x86_64) cp /tmp/libsignal-client-libraries/x86-64/libsignal_jni.so /tmp/libsignal_jni.so ;; \ - *) echo "Unknown architecture" && exit 1 ;; \ - esac; RUN dpkg-reconfigure debconf --frontend=noninteractive \ && apt-get update \ && apt-get -y install --no-install-recommends \ wget software-properties-common git locales zip unzip \ - file build-essential libz-dev zlib1g-dev \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales && \ @@ -43,106 +24,31 @@ RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ ENV JAVA_OPTS="-Djdk.lang.Process.launchMechanism=vfork" -ENV LANG en_US.UTF-8 - -#RUN cd /tmp/ \ -# && git clone https://github.com/swaggo/swag.git swag-${SWAG_VERSION} \ -# && cd swag-${SWAG_VERSION} \ -# && git checkout -q v${SWAG_VERSION} \ -# && make -s < /dev/null > /dev/null \ -# && cp /tmp/swag-${SWAG_VERSION}/swag /usr/bin/swag \ -# && rm -r /tmp/swag-${SWAG_VERSION} - +ENV LANG=en_US.UTF-8 RUN go install github.com/swaggo/swag/cmd/swag@v${SWAG_VERSION} - +# Download pre-built signal-cli release (no source build needed for v0.14.x) RUN cd /tmp/ \ && wget -nv https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz -O /tmp/signal-cli.tar.gz \ && tar xf signal-cli.tar.gz -# build native image with graalvm - -RUN arch="$(uname -m)"; \ - case "$arch" in \ - aarch64) wget -nv https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${GRAALVM_VERSION}/graalvm-community-jdk-${GRAALVM_VERSION}_linux-aarch64_bin.tar.gz -O /tmp/gvm.tar.gz ;; \ - armv7l) echo "GRAALVM doesn't support 32bit" ;; \ - x86_64) wget -nv https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${GRAALVM_VERSION}/graalvm-community-jdk-${GRAALVM_VERSION}_linux-x64_bin.tar.gz -O /tmp/gvm.tar.gz ;; \ - *) echo "Invalid architecture" ;; \ - esac; - -RUN if [ "$(uname -m)" = "x86_64" ]; then \ - cd /tmp \ - && git clone https://github.com/AsamK/signal-cli.git signal-cli-${SIGNAL_CLI_VERSION}-source \ - && cd signal-cli-${SIGNAL_CLI_VERSION}-source \ - && git checkout -q v${SIGNAL_CLI_VERSION} \ - && git apply /tmp/fix-binary-aci.patch \ - && cd /tmp && mkdir -p /tmp/graalvm && tar xf gvm.tar.gz -C /tmp/graalvm --strip-components=1 \ - && export GRAALVM_HOME=/tmp/graalvm \ - && export PATH=/tmp/graalvm/bin:$PATH \ - && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \ - && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' src/main/java/org/asamk/signal/BaseConfig.java \ - && ./gradlew build \ - && ./gradlew installDist \ - && BUILT_LIBSIGNAL_JAR_NAME=$(ls build/install/signal-cli/lib/ | grep 'libsignal-client-.*\.jar' | head -1) \ - && echo "Built libsignal-client jar: ${BUILT_LIBSIGNAL_JAR_NAME}" \ - && rm -rf /tmp/signal-cli-${SIGNAL_CLI_VERSION} \ - && cp -a build/install/signal-cli /tmp/signal-cli-${SIGNAL_CLI_VERSION} \ - && cd /tmp \ - && cp /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/${BUILT_LIBSIGNAL_JAR_NAME} libsignal-client.jar \ - && zip -qu libsignal-client.jar libsignal_jni.so \ - && cp libsignal-client.jar /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/${BUILT_LIBSIGNAL_JAR_NAME} \ - && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source \ - && git apply /tmp/signal-cli-native.patch \ - && ./gradlew -q nativeCompile; \ - elif [ "$(uname -m)" = "aarch64" ] ; then \ - echo "Use native image from @morph027 (https://packaging.gitlab.io/signal-cli/) for arm64 - many thanks to @morph027" \ - && curl -fsSL https://packaging.gitlab.io/signal-cli/gpg.key | apt-key add - \ - && echo "deb https://packaging.gitlab.io/signal-cli focal main" > /etc/apt/sources.list.d/morph027-signal-cli.list \ - && mkdir -p /tmp/signal-cli-native \ - && cd /tmp/signal-cli-native \ - #&& wget https://gitlab.com/packaging/signal-cli/-/jobs/3716873649/artifacts/download?file_type=archive -O /tmp/signal-cli-native/archive.zip \ - #&& unzip archive.zip \ - #&& mv signal-cli-native-arm64/*deb . \ - && apt-get update \ - && apt-get download signal-cli-native=${SIGNAL_CLI_NATIVE_PACKAGE_VERSION} \ - && ar x *.deb \ - && tar xf data.tar.gz \ - && mkdir -p /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile \ - && cp /tmp/signal-cli-native/usr/bin/signal-cli-native /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile/signal-cli; \ - elif [ "$(uname -m)" = "armv7l" ] ; then \ - echo "GRAALVM doesn't support 32bit" \ - && echo "Creating temporary file, otherwise the below copy doesn't work for armv7" \ - && mkdir -p /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile \ - && touch /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile/signal-cli; \ - else \ - echo "Unknown architecture"; \ - fi; - -# Post-processing: inject native libsignal_jni.so and apply BaseConfig workaround. -# On x86_64 the source build (above) already produced a patched installDist with -# the native lib injected, so we only need to package it. On other architectures -# the release tarball is still unpatched — apply the BaseConfig sed workaround and -# inject the native lib there. - -RUN if [ "$(uname -m)" != "x86_64" ]; then \ - ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar \ - || (echo "\n\nsignal-client jar file with version ${LIBSIGNAL_CLIENT_VERSION} not found.\n\n" \ - && ls /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-* && exit 1) \ - && cd /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib \ - && unzip signal-cli-${SIGNAL_CLI_VERSION}.jar \ - && sed -i 's/Signal-Android\/5.22.3/Signal-Android\/5.51.7/g' org/asamk/signal/BaseConfig.class \ - && zip -r signal-cli-${SIGNAL_CLI_VERSION}.jar org/ META-INF/ \ - && rm -rf META-INF \ - && rm -rf org \ - && cd /tmp/ \ - && zip -qu /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal_jni.so; \ - fi - +# Extract the platform-specific native libsignal_jni.so from the release jar +# and re-inject it at the root of the jar (where signal-cli expects it at runtime). +# The release jar bundles per-platform .so files under resource paths; we extract +# the correct one for the build architecture and place it at the jar root. RUN cd /tmp/ \ - && zip -qr signal-cli-${SIGNAL_CLI_VERSION}.zip signal-cli-${SIGNAL_CLI_VERSION}/* \ - && unzip -q /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip -d /opt \ - && rm -f /tmp/signal-cli-${SIGNAL_CLI_VERSION}.zip + && arch="$(uname -m)"; \ + case "$arch" in \ + aarch64) so_name=libsignal_jni_aarch64.so ;; \ + x86_64) so_name=libsignal_jni_amd64.so ;; \ + *) echo "Unsupported architecture: $arch" && exit 1 ;; \ + esac; \ + unzip -jo /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar "$so_name" -d /tmp/ \ + && mv /tmp/$so_name /tmp/libsignal_jni.so \ + && zip -qu /tmp/signal-cli-${SIGNAL_CLI_VERSION}/lib/libsignal-client-${LIBSIGNAL_CLIENT_VERSION}.jar libsignal_jni.so + +RUN cp -r /tmp/signal-cli-${SIGNAL_CLI_VERSION} /opt/signal-cli-${SIGNAL_CLI_VERSION} COPY src/api /tmp/signal-cli-rest-api-src/api COPY src/client /tmp/signal-cli-rest-api-src/client @@ -161,18 +67,13 @@ RUN cd /tmp/signal-cli-rest-api-src && go build -o signal-cli-rest-api main.go RUN cd /tmp/signal-cli-rest-api-src && go test ./client -v && go test ./utils -v # build supervisorctl_config_creator -RUN cd /tmp/signal-cli-rest-api-src/scripts && go build -o jsonrpc2-helper +RUN cd /tmp/signal-cli-rest-api-src/scripts && go build -o jsonrpc2-helper # build plugin_loader RUN cd /tmp/signal-cli-rest-api-src && go build -buildmode=plugin -o signal-cli-rest-api_plugin_loader.so plugin_loader.go # Start a fresh container for release container - -# eclipse-temurin doesn't provide a OpenJDK 21 image for armv7 (see https://github.com/adoptium/containers/issues/502). Until this -# is fixed we use the standard ubuntu image -#FROM eclipse-temurin:21-jre-jammy - -FROM ubuntu:jammy +FROM eclipse-temurin:25-jre-noble ENV GIN_MODE=release @@ -186,35 +87,28 @@ ENV SIGNAL_CLI_REST_API_PLUGIN_SHARED_OBJ_DIR=/usr/bin/ RUN dpkg-reconfigure debconf --frontend=noninteractive \ && apt-get update \ - && apt-get install -y --no-install-recommends util-linux supervisor netcat openjdk-21-jre curl locales \ - && rm -rf /var/lib/apt/lists/* + && apt-get install -y --no-install-recommends util-linux supervisor netcat-openbsd curl locales \ + && rm -rf /var/lib/apt/lists/* COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/signal-cli-rest-api /usr/bin/signal-cli-rest-api COPY --from=buildcontainer /opt/signal-cli-${SIGNAL_CLI_VERSION} /opt/signal-cli-${SIGNAL_CLI_VERSION} -COPY --from=buildcontainer /tmp/signal-cli-${SIGNAL_CLI_VERSION}-source/build/native/nativeCompile/signal-cli /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/scripts/jsonrpc2-helper /usr/bin/jsonrpc2-helper COPY --from=buildcontainer /tmp/signal-cli-rest-api-src/signal-cli-rest-api_plugin_loader.so /usr/bin/signal-cli-rest-api_plugin_loader.so COPY entrypoint.sh /entrypoint.sh -RUN groupadd -g 1000 signal-api \ +RUN (userdel ubuntu 2>/dev/null; groupdel ubuntu 2>/dev/null; true) \ + && groupadd -g 1000 signal-api \ && useradd --no-log-init -M -d /home -s /bin/bash -u 1000 -g 1000 signal-api \ - && ln -s /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli /usr/bin/signal-cli \ - && ln -s /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native /usr/bin/signal-cli-native \ + && ln -sf /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli /usr/bin/signal-cli \ && mkdir -p /signal-cli-config/ \ && mkdir -p /home/.local/share/signal-cli -# remove the temporary created signal-cli-native on armv7, as GRAALVM doesn't support 32bit -RUN arch="$(uname -m)"; \ - case "$arch" in \ - armv7l) echo "GRAALVM doesn't support 32bit" && rm /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native /usr/bin/signal-cli-native ;; \ - esac; - RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ dpkg-reconfigure --frontend=noninteractive locales && \ update-locale LANG=en_US.UTF-8 -ENV LANG en_US.UTF-8 +ENV LANG=en_US.UTF-8 EXPOSE ${PORT}