wire-server: the AGPL Haskell back end behind the Wire messaging app
🇪🇺 Wire back-end services
At a glance
- What is it?
- Eight services, a shared library layer, and a Kafka-free architecture in Haskell, published under AGPL by the company that runs the commercial product. Self-hosting it is documented but federation is not finished.
- Who is it for?
- wire-server is a serious piece of engineering published by a company that clearly wanted it legible, and the service split is clean enough to learn from even if you never deploy it. Whether you can actually run it is a different question.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Haskell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Eight named services instead of one application
The repository is not an application you start. It is a Haskell monorepo of eight services with names borrowed from the shipping industry, and the README lists them plainly:
- nginz: public API reverse proxy, described as Nginx with a custom libzauth module - galley: conversations and teams - brig: accounts - gundeck: push notification hub - cannon: WebSocket push notifications - cargohold: asset storage for images and files - proxy: third-party API integration - spar: single sign-on
Underneath sits a `libs/` directory of shared libraries, a `tools/` directory with database migration tooling and a Swagger-based backoffice tool called stern, and a `build/` area with build scripts and Dockerfiles. The `integration/` directory in the tree holds integration tests, and `deploy/` is described in the README as work in progress for running the server in an ephemeral in-memory demo mode.
That decomposition is the first useful thing to take from the project. Conversation state, account state, asset storage and push delivery are separate programs with separate failure modes, which is the opposite of how most people write a chat back end and the reason the architecture survives real load.
Building the images with make and Docker
There are two build routes and the README is candid about their limits. Docker is the main one, requiring docker version 17.05 or newer and make. The full sequence from a clean checkout is three targets:
make docker-deps docker-intermediate docker-servicesThe first target builds the dependency images, the second the intermediate layers, the third the service images themselves. Ready-built images are available from quay.io if you would rather not start from scratch, and the README warns specifically that the `ubuntu20-builder` image takes a very long time to build. After the first pass, a code change only needs the intermediate and service targets re-run, which is the line the documentation repeats as the fast path.
The alternative is a Nix-provided build environment, which the README restricts to local development and testing and points at the building instructions in the developer documentation. The tree supports that claim: `flake.nix`, `flake.lock`, a `nix/` directory, `hie.yaml` for Haskell IDE Engine configuration, `.ormolu` for formatting, `.hlint.yaml` for linting, and `treefmt.toml` for formatting orchestration. There is also a `weeder.toml`, which is the config for detecting unused Haskell exports.
One memory warning is worth passing along. The README notes that Docker needs plenty of RAM and that an exit code 137 from the builder target is a sign the build ran out of memory, which is the kind of specific operational detail that only appears after someone has hit it.
Deploying through Helm charts, not through this repository
The README offers two installation options and recommends the one that is not in this repository. Option one is wire-server-deploy, a separate repository with configuration and instructions for running wire-server on Kubernetes, and it is the recommended path for self-hosting. Option two is compiling everything here and running `dist/run-services`, which the README describes as intended for trying wire-server on a local development machine and not suited for production.
The charts themselves live in the `charts/` directory and are mirrored to S3, so they can be added as a Helm repository directly:
helm repo add wire https://s3-eu-west-1.amazonaws.com/public.wire.com/chartsThe `Makefile` shows how large the chart surface is. The release list includes `wire-server`, `redis-ephemeral`, `rabbitmq`, `rabbitmq-external`, `databases-ephemeral`, `fake-aws`, `fake-aws-s3`, `fake-aws-sqs`, `aws-ingress`, `fluent-bit`, `kibana`, `backoffice`, `demo-smtp`, `elasticsearch-curator`, `minio-external`, `cassandra-external`, `ingress-nginx-controller`, `reaper`, `k8ssandra-test-cluster`, `ldap-scim-bridge`, `wire-server-enterprise` and `wire-ingress`. A separate integration list adds `wire-ingress-services`.
That list is the answer to whether this is a weekend project. It is not. Cassandra and PostgreSQL, Elasticsearch, RabbitMQ, MinIO or S3, an ingress controller, log shipping into Kibana and an LDAP bridge are all part of a normal deployment. Note also `wire-server-enterprise` in the chart list, which implies a commercial component exists alongside the open source one.
A Cassandra to PostgreSQL migration you can watch in the changelog
The repository publishes dated releases rather than semver tags: `v2026-09-18` with Chart Release 5.36.0, `v2026-08-27` with 5.35.0, and `v2026-07-07` with 5.34.0. The names encode the release date, and the chart version is the thing you would actually pin.
The release notes are unusually detailed about things breaking. In the September release, `preventAdminlessGroups` is unlocked by default, API version v18 is finalized and v19 opened, the default `totalLimitBytes` changed from one terabyte to unlimited, meeting events now go to all push channels including native push via APNs and FCM, and user data can be migrated from Cassandra to PostgreSQL. The August release is largely an operational one: the PostgreSQL connection pool moved to `hasql-resource-pool`, which deprecated the `agingTimeout` setting, and a new background worker subsystem arrived with dispatcher, worker, retry, shutdown and reaper settings, initial queues for `meetings` and `conversations`, and `jobs.workerThreads` defaulting to 1.
Two things an operator should notice in that August note. LISTEN/NOTIFY is disabled, so the job runner does not open an additional listener connection. And connections are borrowed for active transactions rather than reserved permanently per pool, which means you size the PostgreSQL `max_connections` against workload rather than against worker count.
The repository also has a `changelog.d/` directory, so pending changes are accumulated as fragments rather than written into `CHANGELOG.md` at release time. The July release carries a breaking change of its own: the `meetings` team feature flag is now disabled and locked by default, and API v17 renamed storage quota fields to `totalLimitBytes` and `perUserQuotaBytes` with negative values meaning unlimited, returned as `-1`.
AGPL-3.0, a trademark carve-out, and no federated future yet
The license is AGPL-3.0, which is the more demanding of the two common AGPL cases for a server: if you modify this code and let others interact with it over a network, the AGPL's source-offer obligation reaches that interaction. That is a materially different obligation from MIT or Apache-2.0, and it is the reason the license line in the project metadata is worth reading rather than skimming.
The README adds a second layer. Licensing information lives in the LICENSE file plus a list of third-party licenses at wire.com/legal/licenses, and no license is granted to the Wire trademark or its logos, which remain exclusively owned by Wire Swiss GmbH and may not be used without prior written consent. So you can read the code and, subject to AGPL, modify it, but you cannot ship it under the Wire name. Third-party license obligations also arrive with the build: the services pull in a large dependency tree, which is why that separate list exists.
The other limitation is scope. The README says federation is on the long-term roadmap. Given the release notes now mention federation support for system notifications with capability-aware handling for older remote backends, some federation work has clearly begun, but the documentation does not present a server you can stand up and expect to federate with the public Wire network. The same README points to a separate wire-docs repository and notes that the `docs/` directory here contains only files modified within the last year, since 19/02/25, with everything else moved out. Documentation therefore lives in two places, which is worth knowing before you go looking for a guide that is not in this tree.
The security assumption in the architecture diagram
The README includes a high-level architecture diagram at `docs/src/developer/developer/architecture/wire-arch-2.png`, and then makes a statement that any serious evaluation has to start from: communication between internal components is currently not guarded by dedicated authentication or encryption and is assumed to be confined to a private network.
That is a reasonable design for a cluster you operate yourself, and it is also the single most important sentence on the page for anyone considering self-hosting. There is no service mesh or mTLS between galley and brig here. The security boundary is the network boundary, which means the Kubernetes cluster configuration, network policies and ingress setup become security-critical code rather than operational detail. The presence of `wire-ingress` and `ingress-nginx-controller` in the chart list is where that boundary is enforced.
The repository also carries a `SECURITY.md` and a `CODEOWNERS` file, both of which are what you would expect from a project whose customer base is a regulated enterprise messaging product. There is no published audit in the repository, so claims about the protocol implementation have to come from the Wire documentation site or from independent reviews rather than from anything here. The `libs/` layer is where the protocol logic lives, and a Haskell codebase of this shape is going to be a demanding thing to audit yourself if you are relying on it for something regulated.
Editorial conclusion
wire-server is a serious piece of engineering published by a company that clearly wanted it legible, and the service split is clean enough to learn from even if you never deploy it. Whether you can actually run it is a different question. The README recommends the separate wire-server-deploy repository for anything resembling production and calls the local `dist/run-services` path suitable only for trying it out, and federation remains on the long-term roadmap rather than in the code. Before committing, check three things: whether your users need to reach Wire users on other servers, whether AGPL-3.0 is acceptable for your deployment, and whether the eight services plus Cassandra, Postgres and RabbitMQ fit your operational capacity. Start from the Administrator's Guide at docs.wire.com and the Helm chart repository, not from this README.
Frequently asked questions
What is wire-server and what services does it contain?
It is the source code for the Wire server back end, written in Haskell and released under AGPL-3.0. The README lists eight services: nginz as the public API reverse proxy, galley for conversations and teams, brig for accounts, gundeck for push notifications, cannon for WebSocket push, cargohold for asset storage, proxy for third-party API integration, and spar for single sign-on.
How do you build the wire-server Docker images?
With docker 17.05 or newer and make, run make docker-deps docker-intermediate docker-services from the repository root. Ready-built images are available on quay.io, and the README warns that the ubuntu20-builder image takes a very long time to build and that Docker needs a lot of RAM.
Can I self-host wire-server on Kubernetes?
Yes, and the README recommends it, but through a separate repository. Option one is wire-server-deploy, which holds the configuration and instructions for a Kubernetes deployment. Compiling this repository and running dist/run-services is described as suitable only for local experimentation, not production.
What license is wire-server released under?
AGPL-3.0, with a LICENSE file in the repository root and a separate list of third-party licenses on wire.com. The Wire trademark and its logos are explicitly excluded and remain owned by Wire Swiss GmbH.
Does wire-server support federation with other Wire servers?
Not as a finished feature. The README states that federation is on the long-term roadmap, though recent release notes mention federation support for preventAdminlessGroups system notifications with capability-aware handling for older remote backends.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wireapp-wire-server)