barats/xlistman: xListman - A one-binary, self-hosted mailing list manager. A self-contained alternative to GNU Mailm

github.com · 2026-08-21 · by Long Nguyen ·github
xListman - A one-binary, self-hosted mailing list manager. A self-contained alternative to GNU Mailman. - barats/xlistman

barats/xlistman

xListman - A one-binary, self-hosted mailing list manager. A self-contained alternative to GNU Mailman. - barats/xlistman

1 stars · 0 forks

README

xListman A one-binary, self-hosted mailing list manager. A modern, self-contained alternative to GNU Mailman: manage mailing lists, subscriptions, archives, and moderation from a passwordless web UI and a CLI, delivered as a single static binary with an embedded frontend and SQLite storage.

One binary, no services. Go daemon + embedded SvelteKit web UI + SQLite. Drop it on a VPS or run the container; no separate database, cache, or frontend server. No passwords anywhere. Sign-in is passwordless: one-time magic links emailed to the subscriber, backed by short-lived sessions. MTA-native. Receives mail over LMTP (Postfix and exim validated) or a pipe-mode socket; delivers outbound through a persistent, retrying queue. Full lifecycle. Double opt-in, four-state subscriptions, digests, VERP bounce tracking with auto-disable, held-message moderation, an immutable audit trail, CSV member import/export, and attachment policies.

Features Mailing lists

Virtual domains hosting multiple lists; discussion and newsletter list types Email-driven workflows: subscribe, confirm, post, unsubscribe, bounce handling, and -request commands (which, set digest, …) — all by writing to listname+role@domain Double opt-in subscription confirmation; open / moderated / closed subscription policies Per-list settings: moderation, subject prefix, footer, digest frequency, reply-to mode, max message size, attachment policy, archive retention, and configurable welcome/goodbye/notice emails

Moderation & roles

Held-message moderation (approve / reject / discard) from email, CLI, and web Roles: Owner, Moderator, Designated Sender (newsletter allowlist), and instance-wide Administrator — the web console surfaces what you can do Immutable audit trail of every privileged action, surfaced on the web and CLI

Delivery

Persistent outbound queue with exponential backoff; posts bounce to the sender at max retries Daily or weekly digests (multipart/digest), compiled from the archive VERP envelope senders attribute bounces to the right subscription; auto-disable after a configurable threshold, with owner notification

Web UI

Public: list index and info with subscribe forms Member self-service: manage subscriptions, delivery preference (regular / digest / nomail), re-enable, unsubscribe Members-only archives: threaded browsing, full-text search (SQLite FTS5), MIME-aware rendering with sanitized HTML and attachment downloads Per-list admin console (settings, members, roles, moderation, allowlist, bounces, audit) and a server-admin area (domains, lists, administrators)

Operations

CLI parity for administration: xlistman domain|list|owner|subscriber|… YAML config with environment overrides and ${ENV_VAR} secret expansion systemd unit and a multi-stage scratch-based Docker image included

Screenshots Captured from a live instance seeded with demo data — reproduce them with scripts/screenshot-seed.sh. Click a thumbnail to open it full size.

Public list index Member self-service Members-only archives Moderation queue Server administration

Quickstart Option 1 — Docker (fastest) docker run -d --name xlistman \ -p 8080:8080 -p 8024:8024 \ -v xlistman-data:/data \ -e XLISTMAN_WEB_BASE_URL=http://localhost:8080 \ ghcr.io/barats/xlistman:0.1.0 The image ships a working default config (/etc/xlistman/config.yaml); any value can be overridden with XLISTMAN_* environment variables (e.g. point XLISTMAN_SMTP_HOST / XLISTMAN_SMTP_PORT at your relay). See Configuration. Option 2 — Build from source Prerequisites: Go 1.25+, and Node.js + pnpm for the embedded web UI. cd web && pnpm install && pnpm build # build the SvelteKit frontend cd .. && go build -o xlistman . # then the Go binary (UI embedded) ./xlistman config init # generate ./xlistman.yaml, then edit it ./xlistman serve

The web UI is generated and not committed, so go install github.com/barats/xlistman@latest (and a plain go build) produces a binary without the web UI — CLI and mail handling only. For the full product, use the Docker image (above) or download a release binary from the GitHub Releases page, which ships the frontend embedded (goreleaser builds it as part of the release).

First steps

create a domain, then a list with its first owner

xlistman domain add example.com "Example domain" xlistman list create dev@example.com --type discussion --owner you@example.com xlistman serve # start the daemon (HTTP :8080, LMTP :8024, pipe socket) Open http://localhost:8080, request a login link, and you're in. To receive mail, wire your MTA to deliver the list domain over LMTP (see below). MTA integration xListman integrates with an existing mail server rather than replacing it. The flow: your MTA accepts mail for the list domain and hands it to xListman over LMTP (or the pipe-mode Unix socket); xListman delivers outbound mail back through your relay.

Postfix: virtual_mailbox_domains = lists.example.com + virtual_transport = lmtp:[127.0.0.1]:8024 exim: a manualroute router sending the list domain to an smtp transport with protocol = lmtp on 127.0.0.1:8024

Both configurations are exercised end-to-end against live local instances, including the VERP bounce reverse leg. The reproducible harnesses live in validate/. Configuration Configuration is YAML, loaded from xlistman.yaml (or XLISTMAN_CONFIG), overlaid with XLISTMAN_* environment variables, and expanded for ${ENV_VAR} secrets. A minimal runnable config ships as config.default.yaml; generate a fully commented one with xlistman config init.

Area Key settings

HTTP / LMTP / socket http.listen, lmtp.listen, socket.path

Storage database.path

Outbound smtp.host, smtp.port, smtp.username/password, smtp.mode (smtp|sink), smtp.sink_dir

Web web.base_url (public origin used in emails)

Protection rate_limits.* (subscribe / magic-link / posts per hour)

Delivery queue.max_retries

See internal/config/config.go for the full list of environment variable names. Documentation

CONTEXT.md — the domain model and glossary (Subscriber, Subscription, List Role, Held Message, …) docs/PLAN.md — build history and roadmap docs/adr/ — 26 architecture decision records validate/README.md — MTA validation harnesses SECURITY.md — security policy and reporting

Project status Active, pre-1.0. Versioned with semantic versioning; 0.x indicates the storage/config surface may still evolve. See the Next section in docs/PLAN.md for the roadmap. License MIT © 2026 Barat Semet

source

github.com · 5 images · 116 links

Comments (0)

No comments yet