# Custom signal-cli-rest-api image with signal-cli 0.14.1 # # signal-cli 0.14.1 ships pre-built as two standalone binaries: # signal-cli--Linux-client.tar.gz → single file "signal-cli-client" (JVM) # signal-cli--Linux-native.tar.gz → single file "signal-cli" (native/GraalVM) # # We pull the REST API Go binaries from the upstream bbernhard image and # layer in the 0.14.1 native binary. ARG SIGNAL_CLI_VERSION=0.14.1 ARG BBERNHARD_TAG=latest # ── Stage 1: REST API binaries from upstream ─────────────────────────────── FROM docker.io/bbernhard/signal-cli-rest-api:${BBERNHARD_TAG} AS restapi # ── Stage 2: runtime image ───────────────────────────────────────────────── FROM ubuntu:noble ARG SIGNAL_CLI_VERSION ENV GIN_MODE=release ENV PORT=8080 ENV SIGNAL_CLI_CONFIG_DIR=/home/.local/share/signal-cli ENV SIGNAL_CLI_UID=1000 ENV SIGNAL_CLI_GID=1000 ENV SIGNAL_CLI_CHOWN_ON_STARTUP=true ENV SIGNAL_CLI_REST_API_PLUGIN_SHARED_OBJ_DIR=/usr/bin/ ENV LANG=en_US.UTF-8 # Runtime deps (openjdk-21 for JVM fallback, supervisor for json-rpc mode) RUN apt-get update \ && apt-get install -y --no-install-recommends \ util-linux supervisor openjdk-21-jre wget curl locales \ && sed -i '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 \ && rm -rf /var/lib/apt/lists/* # Copy REST API binaries from upstream image COPY --from=restapi /usr/bin/signal-cli-rest-api /usr/bin/signal-cli-rest-api COPY --from=restapi /usr/bin/jsonrpc2-helper /usr/bin/jsonrpc2-helper COPY --from=restapi /usr/bin/signal-cli-rest-api_plugin_loader.so /usr/bin/signal-cli-rest-api_plugin_loader.so COPY --from=restapi /entrypoint.sh /entrypoint.sh COPY --from=restapi /etc/supervisor /etc/supervisor # Download signal-cli 0.14.1 binaries. # The tarballs each contain a single file (no subdirectory). # native tarball → file named "signal-cli" # client tarball → file named "signal-cli-client" RUN mkdir -p /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin \ \ # Native binary (GraalVM compiled, no JVM needed) && wget -q "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-native.tar.gz" \ -O /opt/signal-cli-native.tar.gz \ && tar xzf /opt/signal-cli-native.tar.gz -C /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/ \ && mv /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli \ /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native \ && chmod +x /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native \ && rm /opt/signal-cli-native.tar.gz \ \ # JVM client (used when MODE != native, and as "signal-cli" wrapper) && wget -q "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-client.tar.gz" \ -O /opt/signal-cli-client.tar.gz \ && tar xzf /opt/signal-cli-client.tar.gz -C /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/ \ && mv /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-client \ /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli \ && chmod +x /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli \ && rm /opt/signal-cli-client.tar.gz \ \ # Symlinks to /usr/bin (expected by signal-cli-rest-api) && ln -sf /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli /usr/bin/signal-cli \ && ln -sf /opt/signal-cli-${SIGNAL_CLI_VERSION}/bin/signal-cli-native /usr/bin/signal-cli-native # User + directories (mirror upstream; remove default ubuntu user first) RUN userdel ubuntu -r 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 \ && mkdir -p /home/.local/share/signal-cli /signal-cli-config EXPOSE ${PORT} ENTRYPOINT ["/entrypoint.sh"] HEALTHCHECK --interval=20s --timeout=10s --retries=3 \ CMD curl -f http://localhost:${PORT}/v1/health || exit 1