Self Deploy the Latest Version of Signal Server v20250822.0.0

Graduated from Telkom University with a degree in Computer Science, specializing in software development and systems design. Recently contributed to Supernova Palapa Nusantara as a Software Engineer, where efforts focused on developing and implementing software solutions, improving project reliability, and collaborating with multidisciplinary teams. Key competencies include software architecture, quality assurance, and backend programming.
At Supernova Palapa Nusantara, contributed to software architecture enhancements with a focus on system reliability and project goals. Previous roles involved optimizing and developing web platforms, such as university systems, in collaboration with cross-functional teams. Brings a collaborative approach and a commitment to delivering impactful digital solutions that align with organizational objectives.
Introduction
Signal has become one of the most trusted messaging platforms in the world, well known for its strong emphasis on privacy and security. Unlike many other messaging apps, Signal implements end-to-end encryption by default, ensuring that no one—not even the Signal team—can access the content of your conversations. This commitment to security and user freedom is one of the main reasons why individuals, organizations, and even governments rely on Signal for secure communication.
Beyond being a secure messenger, Signal is also open source, which means its codebase is publicly available for anyone to review, audit, and even contribute to. This transparency not only builds trust but also allows developers to experiment with self-hosting their own Signal infrastructure.
However, while the idea of running your own Signal server sounds exciting, the reality is far from simple. As highlighted in SoftwareMill’s article, deploying the Signal server is highly complex, requiring significant technical knowledge, specific dependencies, and ongoing maintenance to keep it in sync with Signal’s rapid development cycle.
To make matters more complicated, if you search for tutorials online with the keyword “how to deploy signal server”, most of what you’ll find is outdated. Signal’s server code has evolved drastically over the years, rendering older guides nearly useless. Many of those instructions no longer apply to the current architecture or dependencies of Signal Server.
Despite all these challenges, I managed to successfully deploy the latest version of Signal Server (v20250822.0.0). If you are interested in deploying Signal on your own infrastructure—whether for research, personal use, or within your company—you don’t have to start from scratch. You can reach out to me for guidance and support in setting up your own secure Signal environment.
Before You Start
In recent years, Signal has shifted much of its infrastructure to rely heavily on cloud-based services. This transition makes sense, as it allows Signal to scale globally and handle millions of concurrent users with high availability. Many of the critical components that power Signal—such as messaging queues, storage layers, and push notification services—are tightly integrated with cloud platforms.
For anyone attempting to run Signal Server on their own, this introduces some important considerations. Even if your goal is to deploy Signal locally, you will still need access to several of these cloud services. The good news is that many providers offer a free tier, which can be leveraged to set up a working environment without incurring high costs. With some careful configuration, it is possible to replicate much of the production setup while staying within free usage limits.
If your objective is to run Signal in a fully local environment, things become more complicated. This typically requires either modifying third-party code or setting up self-hosted replacements for cloud services using tools like LocalStack. While this is certainly achievable, it adds significant complexity and can make maintenance much more difficult in the long run.
In this article, we will take a more practical approach: deploying the latest version of Signal Server without heavily modifying its dependencies or services. The focus will be on getting Signal up and running with minimal adjustments, making it possible for you to experiment with a self-hosted deployment while still understanding how Signal’s infrastructure pieces fit together.
Preparation & Requirements
Before diving into the deployment steps, it’s important to understand the foundational requirements for running Signal Server. A successful deployment doesn’t just depend on the main server itself. It involves hardware, multiple cloud services, domain configurations, and a variety of supporting components. Below are the key elements you’ll need to prepare:
Hardware
For this deployment, I used a VPS running Ubuntu 24 with specifications of 4 CPU cores and 8 GB RAM. This provides enough resources to handle the compilation, dependencies, and basic operation of Signal Server.
Cloud Services
Signal relies heavily on cloud infrastructure. In our setup, we will be using:
AWS (DynamoDB, S3, etc.)
GCP (Firebase, Google Cloud Storage, etc.)
Cloudflare for DNS and security layers
…and several other services that integrate into the overall system.
Domain
Signal itself makes use of multiple subdomains for different services. While
chat.signal.orgacts as the main messaging endpoint, other subdomains such asstorage.signal.org,svr.signal.org, and various TURN servers support additional functionality. A proper domain setup is crucial to mirror this architecture in your self-hosted deployment.Other Services
It’s important to note that the Signal Server is only the core service. Many smaller supporting services such as storage, push notifications, and real-time communication helpers must be integrated for the system to function correctly. We will explore these dependencies in more detail later in this guide.
Get the Source Code
Signal Server’s code is available on GitHub:
git clone https://github.com/signalapp/Signal-Server.git
After cloning, switch to the latest version first (in this case v20250822.0.0). You can find the available versions in the GitHub repository under the tags section.
git checkout -b latest v20250822.0.0
git log
commit dbbd9134455affb83b350bb2121e4c8dc39dac0b (HEAD -> latest, tag: v20250822.0.0)
Author: Ravi Khadiwala ravi@signal.org
Date: Fri Aug 22 11:40:16 2025 -0500
Allow downgrade on SQPR capability
Build and Run
Signal Server is written in Java, and the latest release requires Java 24 (Temurin distribution) along with Maven (mvn) for building the project. Before attempting to compile, make sure both Java and Maven are properly installed and configured in your environment, as mismatched versions or missing dependencies will cause the build process to fail.
cd Signal-Server
mvn clean install -DskipTests

Once the compilation is complete, you will find the generated TextSecureServer-20250822.0.0.jar file located in the service/target directory. This JAR file serves as the main executable for running the Signal Server. From this point onward, it becomes the core binary you’ll use to start and manage your self-hosted Signal instance. Try to run it:
java -jar service/target/TextSecureServer-20250822.0.0.jar server
After trying to run the server, I encountered the error:
no main manifest attribute, in service/target/TextSecureServer-20250822.0.0.jar.
After a moment of reflection (and questioning my life choices), I discovered the root cause: there is a module called spam-filter that points to a private repository — https://github.com/signalapp/Signal-Server/blob/main/spam-filter. Since this repository is private, we don’t have access to it.
It seems that this module is intentionally private because it contains critical features related to spam protection, including spamChecker, challengeConstraintChecker, registrationFraudChecker, registrationRecoveryChecker, and captchaClientSupplier.
To work around this limitation, we need to exclude the module by adding the build flag -Pexclude-spam-filter when compiling the application then run it again.
mvn clean install -DskipTests -Pexclude-spam-filter
java -jar service/target/TextSecureServer-20250822.0.0.jar server

It looks like this time it’s not the same error as before, but rather a missing credentials issue. Inside the service/config folder, there are two configuration files that we need to provide when running the JAR file:
The first one is
sample-secrets-bundle.yml, which we include using the flag:-Dsecrets.bundle.filename=sample-secrets-bundle.ymlThe second one is the main
sample.ymlfile, which is appended at the end of the command afterserver.
So the full command to run Signal Server is:
java -Dsecrets.bundle.filename=sample-secrets-bundle.yml -jar service/target/TextSecureServer-20250822.0.0.jar server sample.yml
After solving that issue, I thought the server would finally run and be ready to use. But reality can be harsh. In fact, this was only the beginning of the Signal Server setup journey. What followed was a cycle of endless trial and error, challenge after challenge—so much so that I started questioning whether I had made the wrong choices in life.
Still, no matter how tough it gets, each obstacle has to be solved one by one—and with a sense of pride for every small victory along the way.
Server Configuration
Based on my review of the sample.yml and sample-secrets-bundle.yml files, here is a summary of the key configuration sections:
Logging: This can be directed to the console. Integration with Datadog can be disabled (since it’s a paid service).
Metrics: Can be directed either to the console or stored in a CSV file.
TlsKeyStore: This can be left as default.
Payments (Stripe, Braintree, Google Play Billing, Apple App Store, PaymentsService): Subscriptions and one-time donations can be left as default or ignored entirely if you don’t need payment integration.
AppleDeviceCheck & DeviceCheck: Leave as default (their exact purpose is unclear for now, so we’ll leave them untouched).
DynamoDB & DynamoDB Tables: This is the core configuration for Signal Server’s database. Proper setup is critical.
pagedSingleUseKEMPreKeyStore: Used to store keys, which must be configured with AWS S3.
Redis Clusters (cacheCluster, pubsub, pushSchedulerCluster, rateLimitersCluster, messageCache): These require Redis in cluster mode. Running this in the cloud can be expensive, so I configured a Redis cluster on a single VM instead (I’ll explain how to set this up later in another article).
directoryV2: Can remain as default. This is related to the Contact Delivery Service.
svr2, svrb, storageService, registrationService, keyTransparencyService: These are supporting services that work alongside the main Signal Server. We’ll discuss them in detail later.
gcpAttachments & tus: Used for attachment uploads.
apn & fcm: Required for push notifications.
cdn & cdn3StorageManager: Handle profile pictures, attachments, and related media.
dogstatsd & openTelemetry: These can be safely ignored.
unidentifiedDelivery, zkConfig, callingZkConfig, backupsZkConfig: These are critical configurations because they are directly tied to libsignal. They must be set up properly.
dynamicConfig: A dynamic configuration stored in AWS S3 that continuously syncs with the application. This is also very important.
Other Services
These are the supporting services that must also be set up for the main Signal Server to run properly. Each of these services has its own configuration, but for now, I’ll just summarize what they are and their functions. I may cover the detailed setup instructions in future articles.
Registration Service: A core dependency that enables users to register. It handles the creation of registration sessions, which require users to verify their phone numbers.
Storage Service: Essential for group functionality. Without this service, users cannot create groups or perform group-related activities.
Coturn: Signal has migrated from self-hosted Coturn to Cloudflare’s TURN service. Fortunately, Cloudflare provides a monthly quota for free usage, and charges only once that quota is exceeded.
Signal Calling Service: While the TURN server handles one-to-one calls, this service enables group calls and video calls. Without it, group calling would not be possible.
Tus: Handles file uploads. Signal is transitioning from Google Cloud Storage (GCS) to this service. For now, you can override it with GCS and safely ignore it, since Tus needs to be deployed on Cloudflare Workers (a paid service).
Contact Discovery Service: A resource-intensive service that requires Intel SGX. Its function is to map user contacts to determine whether they already have a Signal account.
Secure Value Recovery v2: Another SGX-dependent service, responsible for verifying a user’s PIN during account recovery.
Key Transparency Service: Protects against man-in-the-middle attacks by ensuring that the public key received by a client truly belongs to the intended user. It also provides auditability and prevents the server from manipulating keys.
With these services in place, you should have everything needed to run a functional Signal Server. Some services may not be explicitly listed here, as they are used primarily on the client side (mobile and desktop), so additional tracing may be required to identify any missing components.
But with that said, this marks the (hopefully final) milestone in setting up Signal Server. Here’s a screenshot of victory in this battle:

Setting up the latest version of Signal Server is far from a simple task. From dealing with private modules, cloud dependencies, and countless supporting services, the journey requires patience, persistence, and a deep dive into Signal’s evolving architecture. But in the end, the reward is worth it: the ability to run your very own self-hosted instance of one of the most secure messaging platforms in the world.
If you’re interested in deploying Signal Server for research, personal use, or within your organization, you don’t have to go through the same trial-and-error process I did. I can help you streamline the setup and get your own Signal Server running smoothly.
👉 Feel free to reach out to me if you’d like assistance with your Signal Server deployment.





