Install

xListman is a single static binary. You have three ways to get one, in order of ease.

Option 1 — Docker

The container image ships a working default config and the embedded web UI. This is the fastest way to be running.

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

That starts the daemon with HTTP on :8080, LMTP on :8024, and a SQLite database in the xlistman-data volume. The default config lives at /etc/xlistman/config.yaml inside the image; anything can be overridden with XLISTMAN_* environment variables.

Point your browser at http://localhost:8080 and request a login link to confirm it’s alive.

Option 2 — Release binary

Download the archive for your platform from GitHub Releasesdarwin_amd64, darwin_arm64, linux_amd64, or linux_arm64. Release binaries include the embedded web UI. Unpack, then:

./xlistman config init   # generate ./xlistman.yaml, then edit it
./xlistman serve

The systemd unit in the repo (systemd/xlistman.service) shows a production service layout.

Option 3 — Build from source

You need 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

A note on go install

A plain go install github.com/barats/xlistman@latest (or go build without building the web UI first) produces a binary without the web UI — CLI and mail handling only. For the full product, use the Docker image or a release binary. This is a known trade-off of keeping the generated frontend out of the repo; the release pipeline builds and embeds it.

What “running” means

xlistman serve starts everything in one process:

  • the HTTP server and embedded web UI on http.listen (:8080 by default),
  • the LMTP server for inbound mail on lmtp.listen (:8024),
  • the pipe-mode Unix socket at socket.path,
  • the outbound queue worker and the digest worker,
  • an hourly sweeper that clears expired held messages, magic links, and sessions.

There is no separate database, cache, or frontend server to start. The one file to keep an eye on is the SQLite database at database.path.

Next: First steps — create a domain, a list, and your first owner.