Skip to content

Sync and the daemon

antiphond is the only part of Antiphon that ever touches the network. It syncs mail in, replays your changes out, sends the outbox, files drafts, runs delivery rules, sends desktop notifications and owns the vault. It is an ordinary foreground process: it does not fork, it logs to stdout/stderr, and it shuts down cleanly (sealing the vault) on SIGHUP, SIGINT or SIGTERM. That makes it a first-class citizen under any supervisor, and trivially scriptable everywhere else.

Ready-made service files ship in dist/.

What a sync pass does

Every pass fetches new mail per folder, then periodically sweeps each folder's full UID listing so messages deleted or moved by another client disappear locally too; a UIDVALIDITY change refetches the folder outright rather than trusting any local state. Between fetches, the pass replays your queued operations (flags, moves, deletes), drains the outbox over SMTP or Graph, and pushes spooled drafts to the server's drafts folder.

Passes run on the [sync] interval (two minutes by default), whenever a client asks, and, with push enabled, whenever the server announces something new:

[sync]
interval_minutes = 2
idle = true

With idle = true the daemon parks one IMAP IDLE connection per account on its INBOX and turns every server push into an ordinary pass, so new mail typically lands within seconds. Watchers cost one extra connection per account, re-issue inside the protocol's half-hour deadline, retreat with capped exponential backoff when the network misbehaves, and fall back silently to the interval against servers without IDLE.

Zero setup: let the client start it

None of the sections below is required. When antiphon finds no daemon it starts one itself (in its own process group, logging to $XDG_STATE_HOME/antiphon/antiphond.log), and that daemon outlives the terminal. Disable with:

[daemon]
autostart = false

A supervisor is still the better home for a daemon you want running before the first client launch, restarted on failure, and stopped at logout.

macOS (launchd)

cp dist/launchd/org.antiphon.antiphond.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/org.antiphon.antiphond.plist

Stop with launchctl bootout gui/$(id -u)/org.antiphon.antiphond. Edit the ProgramArguments path if antiphond is not at /usr/local/bin/antiphond (Homebrew on Apple silicon installs under /opt/homebrew/bin, cargo under ~/.cargo/bin).

systemd (GNOME, KDE and most distributions)

mkdir -p ~/.config/systemd/user
cp dist/systemd/antiphond.service ~/.config/systemd/user/
systemctl --user enable --now antiphond

Logs land in journalctl --user -u antiphond. GNOME and KDE both run a systemd user session, so this is the native route there; it also survives logout when lingering is enabled (loginctl enable-linger).

dinit (Artix, Chimera)

mkdir -p ~/.config/dinit.d
cp dist/dinit/antiphond ~/.config/dinit.d/
dinitctl --user enable antiphond

Requires a user dinit instance (Artix and Chimera start one for login sessions; elsewhere run dinit from your session startup).

runit (Void)

mkdir -p ~/sv
cp -r dist/runit/antiphond ~/sv/

Point a user-level runsvdir at ~/sv. On Void the packaged pattern is a system service supervising your user directory (see the Void handbook on per-user services); anywhere else, runsvdir ~/sv from your session startup does the same. Control with SVDIR=~/sv sv start antiphond and friends.

OpenRC, s6 and everything else

OpenRC's user services (0.56+) and s6 both supervise a plain foreground command; point them at antiphond the same way. On any setup without a user supervisor, fall back to one of the session hooks below or to the client's autostart.

Desktop autostart (KDE, XFCE, LXQt, GNOME)

Every XDG desktop honours the autostart directory:

mkdir -p ~/.config/autostart
cp dist/autostart/antiphond.desktop ~/.config/autostart/

This starts antiphond at login but does not restart it on failure; prefer the systemd/dinit/runit routes where you have them.

Minimal sessions

  • X11 (startx/xinit): add antiphond & to ~/.xinitrc before the window manager line.
  • sway: exec antiphond in ~/.config/sway/config.
  • Hyprland: exec-once = antiphond in hyprland.conf.
  • river: riverctl spawn antiphond in ~/.config/river/init.
  • labwc: antiphond & in ~/.config/labwc/autostart.

Stopping

Any of SIGHUP, SIGINT or SIGTERM stops antiphond gracefully: it finishes the loop iteration, seals the vault, and exits. Supervisors' default stop signals are all fine. antiphon doctor shows whether a daemon is reachable and how many operations it is holding.