Skip to content

Latest commit

 

History

48 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Freehold Mail — lifelong ownership, secure connection

CI OpenSSF Scorecard OpenSSF Best Practices SLSA Build Level 2 SBOM: SPDX Dependabot enabled

Mail server: Rust JMAP native Latest release

Semantic Versioning 2.0.0 Keep a Changelog 1.1.0 Contributor Covenant 2.1 License: MIT Components: AGPL-3.0 Status: pre-1.0

English · Tiếng Việt · 日本語 · 简体中文 · 繁體中文 · ไทย · Bahasa Indonesia · हिन्दी · Français · Español · Português · Русский — English is authoritative, see TRANSLATIONS.md

Freehold Mail

Stop renting your inbox. A complete, self-hosted mail stack — Rust mail server, modern web client.

Freehold: property you own outright, with no landlord and no lease to renew. That is the difference between running this and renting a mailbox from someone whose business model is your data.

The Freehold Mail inbox: folder sidebar, message list and reading pane

Mail server, webmail, and TLS termination — wired together, with an installer that generates your secrets and tells you exactly which DNS records to set. Optional SSO when you want it, absent when you don't.

Status: pre-1.0. The default edition has been tested end to end — a real message travels SMTP → mailbox → IMAP. The SSO edition starts and its database and OIDC discovery are verified on the Keycloak version actually shipped; the browser login flow is not. Read Known gaps before you rely on this.


See it work

The webmail ships a guided tour. This is that tour, recorded against a real stack — the messages are delivered over SMTP and read back over IMAP by scripts/seed_demo.py, not mocked:

Guided tour of the webmail: sidebar, compose, search, message list, reading pane, tags, contacts, settings, keyboard shortcuts

Every image here is regenerated by script, never retouched — see docs/media/README.md for the commands.

Why this exists

Self-hosting email is usually either a weekend of gluing together Postfix, Dovecot, Rspamd, and a webmail — or a hosted mailbox where someone else reads your metadata. Freehold Mail is the third option: one repo that assembles a modern stack you run yourself, on a machine you control. The mail server and webmail are memory-safe languages; nginx and PostgreSQL are C, so "memory-safe" describes the parts we chose, not the whole stack.

What it is: orchestration. Compose files, an nginx config, an installer, and honest docs. What it is not: a fork or a rewrite of anyone's mail server.

Two editions

Edition Includes Login Tested E2E
Full Mail (default) mail server + webmail + nginx native username/password ✅ yes
Mail + SSO the above + Keycloak + PostgreSQL OIDC/SSO ⚠️ partial — stack starts, database and OIDC discovery verified on the shipped Keycloak 26.7.0 (15/15); the browser login round-trip is still not measured. See Known gaps

You never touch Keycloak unless you want SSO; it lives in an optional overlay file.

Quickstart

Requirements: a Linux host with Docker and Compose v2, a domain you control, ports 25/465/587/993/80/443 reachable, and a TLS certificate.

git clone https://github.com/Novaza-ai/freeholdmail && cd freeholdmail
./install.sh

Just rented a server, or about to? Read docs/HOSTING.md first. It goes from a bare VPS to a working mailbox with a verification command at every step, and it names the one thing you cannot fix afterwards: most cheap providers block outbound port 25, which makes mail impossible no matter how well you configure this. It also has measured RAM, CPU and disk figures so you rent the right size rather than guessing.

The installer asks for your edition and domain, then:

  1. generates strong random secrets into .env (mode 600, umask 077 — nothing hardcoded);
  2. pins the container images by digest;
  3. resolves your Let's Encrypt paths (the live/ symlinks don't work inside containers);
  4. brings the stack up and prints the commands to create your first mailbox.

Then create a mailbox and log in at https://<your-domain>:

# domain, then user — the roles field is required, or SMTP AUTH refuses the account
curl -u admin:$STALWART_FALLBACK_ADMIN_SECRET -X POST http://127.0.0.1:8080/api/principal \
  -H 'Content-Type: application/json' -d '{"type":"domain","name":"example.com"}'

curl -u admin:$STALWART_FALLBACK_ADMIN_SECRET -X POST http://127.0.0.1:8080/api/principal \
  -H 'Content-Type: application/json' \
  -d '{"type":"individual","name":"you@example.com","secrets":["<password>"],
       "emails":["you@example.com"],"roles":["user"]}'

Finally set your DNS records — docs/DNS.md has MX, SPF, DKIM, and DMARC.

Architecture

Browser ─HTTPS─▶ nginx ─┬─ /  and  /api/*  ─▶ Bulwark webmail (FE)   :3000
                        ├─ /jmap, /.well-known/jmap ─▶ Stalwart  :8080/JMAP
                        └─ /.well-known/openid-configuration ─▶ Keycloak (SSO edition)
SMTP/IMAP clients ───────────────────────────────▶ Stalwart  :25 :465 :587 :993

/api/* belongs to the webmail, which serves its own configuration and session routes there. Only /jmap and JMAP discovery reach the mail server; its admin API is deliberately not exposed through the proxy.

Every box is an independent, swappable container. Front end to back end is network only — JMAP over HTTP, no code linking. That boundary is what lets this repo be MIT while each component keeps its own license.

How it compares

Freehold Mail Mailu / Mailcow docker-mailserver Google Workspace
Mail server Stalwart (Rust, JMAP-native) Postfix + Dovecot Postfix + Dovecot —
RAM, idle (measured) 218–288 MiB mailcow: 6 GiB min (docs) — —
Webmail included ✅ ✅ ❌ (bring your own) ✅
JMAP ✅ ❌ ❌ ❌
SSO/OIDC ✅ optional edition partial ❌ ✅
You hold the data ✅ ✅ ✅ ❌
Maturity pre-1.0 mature mature commercial

About that RAM row, because a comparison without its caveats is marketing. The 218–288 MiB is docker stats against this stack running idle, over two independent runs — the range is published rather than the prettier single number because the two runs disagreed by 32%. Reproduce it with docker stats --no-stream after docker compose up -d; see docs/HOSTING.md. The 6 GiB is mailcow's own documented minimum, not our benchmark of it. And mailcow is heavier because it does more — ClamAV antivirus alone accounts for roughly 1.3 GB, and SOGo adds CalDAV, CardDAV and ActiveSync. If you want groupware and virus scanning, that 6 GiB is the honest price of those features and you should pay it. The comparison is only fair for someone who wants mail, a web client, and nothing else.

Mailu, Mailcow, and docker-mailserver are excellent and far more battle-tested. Pick Freehold Mail if you specifically want a JMAP-native, Rust mail server with webmail and optional SSO in one place — and note that the mail server is the Rust part: the webmail is TypeScript, and nginx and PostgreSQL are C.

Scope, honestly

Now: mailboxes, SMTP/IMAP/JMAP, webmail, TLS, optional SSO — a credible replacement for a hosted mailbox.

Not now: marketing/bulk email, newsletters, shared team inboxes, ticketing, migration tooling from other providers, or a managed control panel. Bulk sending in particular is a deliverability discipline, not a feature toggle — don't assume it.

Roadmap: see ROADMAP.md — near term is trustworthiness (SSO verified on the shipped Keycloak, current upstream mail-server line, deliverability measured on a real domain). Further out is Agentic Mail (v0.3): a stack a software agent can be given safely — an MCP server over JMAP, and scoped, revocable per-agent credentials instead of handing a bot your password. None of it is built yet, which is why the milestone carries that name and the product does not. Contributions on the agent work are wanted — see "Help wanted" in the roadmap.

⚖️ License

  • This repo (orchestration, config, installer, docs): MIT — see LICENSE.
  • The programs it deploys keep their own licenses and are pulled as published images; this repo contains none of their source:
    • Stalwart Mail Server — AGPL-3.0-only OR SELv1 (dual-licensed; not "or later")
    • Bulwark Webmail — AGPL-3.0-only
    • Keycloak — Apache-2.0 (SSO edition)
    • PostgreSQL — PostgreSQL License (SSO edition)
    • nginx — BSD-2-Clause

If you modify Stalwart or Bulwark and serve it to others, AGPL requires you to publish that component's modified source. Running the unmodified images does not. Details: THIRD_PARTY_LICENSES.md and NOTICE.

Security

Open relay is denied, submission requires authentication, and password mechanisms (PLAIN/LOGIN) are only offered after STARTTLS. Each of these was measured against a running stack. There are also real weaknesses you must plan around, including an upstream admin API that returns account passwords in cleartext. Read SECURITY.md before exposing this to the internet.

Tests and operations

Both are in the repo — you can reproduce every claim above yourself:

tests/test_config.sh      # static: both editions validate, no secrets, digests pinned … (~seconds)
tests/test_e2e.sh         # real: stack up → send a message → read it back over IMAP (~2 min)
tests/test_e2e.sh --sso   # same, plus Keycloak + PostgreSQL

test_e2e.sh builds a throwaway stack on loopback-only ports with its own volumes and container names, and tears it down on exit — it will not disturb a running deployment. See tests/README.md, including what these tests deliberately do not cover.

Day-2 operations — backups, certificate renewal, mailbox management, upgrades, incident playbooks — are in docs/RUNBOOK.md. Prerequisites are in docs/REQUIREMENTS.md.

Contributing

See CONTRIBUTING.md. One house rule: claims about runtime behaviour need measurements, not "works on my machine".

Who decides what, how to become a maintainer, and what happens to you if this project is ever abandoned: GOVERNANCE.md. Who to expect a reply from, and an honest statement of the bus factor: MAINTAINERS.md.

Who builds this

Led by Daika Ginza — GitHub · Substack · LinkedIn — with @anhkk1245, at Novaza Solution JSC.

We run this stack's components (Stalwart and Bulwark) in production for our own mail, and we built Freehold Mail to package that architecture for anyone who wants to self-host it. MIT-licensed; see LICENSE and NOTICE.

Full team, how decisions get made, and how to join: MAINTAINERS.md · GOVERNANCE.md.

On commit authorship. Commits are authored by the person who made them, using an email verified on their GitHub account. Copyright is separate and does not change: LICENSE and NOTICE name Novaza Solution JSC. Earlier commits were made under the company identity, Novaza Solution JSC <admin@novaza.ai>. That address is verified on no GitHub account for a while, so those commits were credited to nobody and the Contributors list showed only dependabot. Verifying the address on a maintainer's account fixed all fifteen at once, without touching the commits. If you contribute, commit with an email verified on your own account and you will be credited. MAINTAINERS.md has the commands.


Not affiliated with Stalwart Labs, the Bulwark project, or Keycloak.

About

Own your email. A complete self-hosted mail stack — Rust mail server, modern web client, optional SSO. MIT orchestration around AGPL components.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages