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 Releases — darwin_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(:8080by 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.