Skip to content
AnonyfoxPublic

About

Self-hosted mail server and newsletter platform in one Go binary: mailboxes, double opt-in lists and list websites for many domains on a $5 VPS, run by your AI agent through a JSON CLI. DKIM, SPF, DMARC, MTA-STS built in.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

lfr

CI codecov Release Go Reference License: MIT

lfr is a self-hosted mail server and newsletter tool in one Go binary for people running custom domain mailboxes and Markdown newsletters through a terminal or coding agent. An idle server with one domain and one list used about 25 MB of memory in the measurement documented in operations.

curl -fsSL https://lfr.email/install.sh | sudo sh

lfr setup on a fresh server, lfr domain add printing the ten DNS records for example.com, then a first mailbox

On the server it goes to /usr/local/bin. Without sudo it installs to ~/.local/bin, which is enough on a machine that only drives a server over ssh.

An agent operates lfr through its CLI, on the server or over ssh. It runs as one Go process with SQLite, without an admin UI or remote API.

  • A mail server: any name@domain in seconds, aliases, catch-alls, plus-addressing, forwarding, full-text search, replies, and a spam filter that learns from every message you move. DKIM (RSA and Ed25519), SPF, DMARC, MTA-STS and TLS reporting for every domain; lfr domain add prints exactly the DNS records to publish and lfr doctor checks them.
  • Newsletters: lists with double opt-in and stored consent proof, a welcome issue, issues written in Markdown with their images, checked before sending, rendered per reader with one-click unsubscribe (RFC 8058) and unsubscribe by reply, click and reply counts, bounce and complaint handling that pauses a list before it hurts your domains. Each list gets a fast website (issues, archive, feed, signup) on its own host with HTTPS.
  • A writing floor: every issue is held to its newsletter's brief and to rules against the habits of generated prose, with an offline estimate of whether AI-text detectors would flag it. The rules and the agent skills rest on built-in research (lfr evidence): 136 reader and writer voices, 20 newsletters and 144 standards, studies and benchmarks, quoted verbatim.

How it compares

The lfr.email comparison covers hosting, storage and export access:

  • lfr runs Markdown newsletters, signup pages, archives and feeds on your own server; Substack provides a hosted publishing network and paid subscriptions.
  • lfr has no per-subscriber software charge. You pay for your server, domain and any outbound relay.
  • Choose a hosted service if you want someone else to manage DNS, backups and sender reputation.
  • Choose a publishing platform if you need built-in paid memberships or a reader discovery network.

Install

The script at the top installs the latest release for Linux and macOS, amd64 and arm64, after checking it against the release checksums. With Homebrew: brew install anonyfox/tap/lfr. With Go 1.26 or newer: go install github.com/Anonyfox/lfr/cmd/lfr@latest.

1. A mail server

On the server (a DigitalOcean droplet named mail.example.com, for example):

sudo lfr setup --hostname mail.example.com --acme-email you@example.com --systemd
lfr domain add example.com            # prints every DNS record to publish
lfr domain dns example.com --check    # every record ok?
lfr doctor                            # reverse DNS, blocklists, outbound, certificates, disk, queue

setup creates /var/lib/lfr, a system user and a hardened systemd service allowed to bind ports 25, 80 and 443. On Cloudflare, set the records to "DNS only"; lfr domain dns example.com --zone prints them as a zone file Cloudflare imports.

lfr delivers straight to recipients' mail servers when outbound port 25 is open. Many cloud providers block it; DigitalOcean blocks ports 25, 465 and 587 on every droplet. Then lfr hands finished, DKIM-signed messages to a relay on an alternate port for the last hop:

echo "$SES_SMTP_PASSWORD" | lfr relay smtps://AKIA...@email-smtp.eu-central-1.amazonaws.com:2465 --spf include:amazonses.com
lfr relay       # the route, a login test, and webhook URLs for the relay's bounce notifications

Amazon SES costs $0.10 to $0.16 per 1,000 messages; SMTP2GO has a free tier. See operations for both.

2. Mailboxes

lfr mailbox add hello@example.com --name "Example"
lfr mailbox alias hi@example.com hello@example.com
lfr mail ls --unread
lfr mail read 42
lfr mail reply 42 --md - <<< "Thanks, Ann. Feed it twice a day."
lfr mail mv 43 spam             # teaches the spam filter
lfr events --follow             # new mail, bounces, signups as they happen

3. Your agent

lfr skills install              # setup, mailbox, research, concept, launch, issue, learn
export LFR_REMOTE=you@mail.example.com   # every command, from your laptop, over ssh

Every command accepts --json; exit codes are 0 (ok), 1 (failed), 2 (wrong usage or invalid input) and 3 (server not running). Human output ends with Next: and the step that usually follows. SKILL.md is the entry point for agents.

4. A newsletter

The list lives on the server; the newsletter's editorial work lives in a project folder:

lfr list add bakers --name "Bakers Weekly" --from news@example.com --host news.example.com
lfr init bakers --list bakers --owner you@example.com
cd bakers && lfr check          # names the next step and its skill, every time

lfr check walks a newsletter through research (readers' verbatim voices, peer newsletters), the brief (concept.md: promise, cadence, format, length, subjects, voice, guardrails), the launch (lfr push copies the promise, cadence and welcome issue to the list), and then every issue: plan, draft, fix, test, approve, send, learn. Issues are Markdown files, with images next to them:

---
subject: Why your starter smells like nail polish
preheader: It is hungry, not dead, and two feeds fix it
idea: I001
---
# Your starter is hungry

It smells of acetone because it ran out of food. Feed it twice a day.

![The starter after two feeds, doubled in its jar](images/starter-day-2.jpg)
lfr issue put issues/acetone.md                 # create or update by slug, upload its images
lfr issue test acetone you@example.com
lfr issue send acetone --at 2026-10-23T07:00:00+02:00
lfr issue show acetone --learn                  # the learnings.md entry, two days later

Readers sign up at https://news.example.com/ (or any form that posts email to /subscribe), confirm by clicking a button, and leave with one click. Published issues live at /issues/<slug>. lfr site bakers --eject site copies the website templates into the project for editing and lfr push uploads them; lfr rules lists every check with the research behind it.

FAQ

Can I run a mail server and newsletters in one Go binary?

lfr combines custom domain mailboxes, mailing lists and newsletter websites in one process with SQLite. The CLI manages mail, readers and Markdown issues locally or over ssh.

What server do I need to self-host lfr?

The operations guide specifies a Linux server with a public IPv4 and says 512 MB of memory is plenty. Open inbound ports 25, 80 and 443, and publish the DNS records printed by lfr domain add.

Can lfr send newsletters if my VPS blocks outbound port 25?

Yes. Configure an SMTP relay: lfr builds and DKIM-signs messages, then hands them to the relay for the last hop. See operations for Amazon SES and SMTP2GO setup.

Does lfr support double opt-in and one-click unsubscribe?

Yes, with stored consent proof, RFC 8058 one-click unsubscribe and unsubscribe by reply. It also handles bounces and complaints and pauses lists when their rates exceed its limits.

Can my coding agent manage lfr from my laptop?

Yes. Set LFR_REMOTE as shown above to run commands over ssh; every command accepts --json. SKILL.md is the agent entry point, and lfr skills install installs the process skills.

Documentation

  • Architecture: packages, data, the request paths.
  • AGENTS.md: how to change things: a command, a migration, a rule, a skill.
  • Operations: DNS, relays, deliverability, backups, upgrades, troubleshooting.
  • Contributing: building, testing, fuzzing, releasing.
  • The lfr.email Grok Bot: the handoff a Grok Bot follows to set up and share it.

MIT licensed.

About

Self-hosted mail server and newsletter platform in one Go binary: mailboxes, double opt-in lists and list websites for many domains on a $5 VPS, run by your AI agent through a JSON CLI. DKIM, SPF, DMARC, MTA-STS built in.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages