Files
docs-alpha.jayfield.org/MAIL-ACCOUNTS.md
T
jensandClaude Sonnet 5 92d871f2da Initial docs: alpha.jayfield.org server documentation
Records the host's service inventory, setup runbook, mail account list,
sync plan, package diff vs. clean install, and hardening TODOs, including
today's SSH hardening (key-only, no root login) and the fail2ban sshd
findtime fix for a low-and-slow brute-force evasion pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RdTyvEJkfNLDVAWt8WQ6X9
2026-07-19 23:09:27 +02:00

5.5 KiB

alpha.jayfield.org — Adding Email Accounts (How-To)

Accounts, aliases, and domains for the mail stack (Postfix + Dovecot) all live in one place: the vmail MySQL database on this host. There's no admin UI — everything below is a mysql insert plus one hash-generation command. See SETUP.md §3 for how this schema was built in the first place; this doc is just the day-to-day "add a mailbox" recipe.

No service restart is ever needed for account changes. Postfix and Dovecot query MySQL live on every delivery/login (auth_cache_size is unset/disabled on this host — verified in /etc/dovecot/conf.d/10-auth.conf) so a new row is usable immediately.

1. Prerequisite: the domain must already exist

sudo mysql vmail -e "SELECT * FROM domains;"

Currently just jayfield.org. If you ever need a second domain, insert it here first (INSERT INTO vmail.domains (domain) VALUES ('newdomain.tld');) — but note that's the easy part; a real second domain also needs its own DNS zone/MX/SPF/DMARC records and DKIM selector (see SETUP.md §2/§3), a TLS cert covering it, and its own mynetworks/inet_interfaces consideration. Out of scope for just adding a mailbox — this doc assumes jayfield.org.

2. Generate the password hash

Never put a plaintext password in the accounts table — hash it first:

sudo doveadm pw -s SHA512-CRYPT

(You'll be prompted twice, interactively — don't pass the password as a CLI argument, it'd land in shell history.) Copy the full {SHA512-CRYPT}$6$... output; that's the exact string that goes in the password column.

You may see Error: net_connect_unix(/run/dovecot/stats-writer) failed: Permission denied printed before the hash — that's doveadm trying to report stats, unrelated to the hash it prints right after; harmless, not a sign the hash is wrong.

3. Insert the account

sudo mysql vmail -e "INSERT INTO accounts (username, domain, password, quota, enabled, sendonly) VALUES ('newuser', 'jayfield.org', '{SHA512-CRYPT}\$6\$...', 2048, 1, 0);"
  • quota is in MB (existing accounts use 2048 = 2GB — match that unless there's a reason not to).
  • enabled = 1 — required for the account to authenticate or receive mail at all. Setting it to 0 disables the account without deleting it (see §6).
  • sendonly = 0 — normal mailbox: can send and receive. Set to 1 only for a send-only address that should never accept incoming mail (see §5).

That's it — no mailbox directory to create by hand. Dovecot auto-creates /var/vmail/mailboxes/jayfield.org/<user>/mail/ (owned vmail:vmail, 700) the first time the account logs in or receives mail.

4. Client configuration (no webmail — this stack is IMAP/SMTP only)

Setting Value
IMAP (recommended) mail.jayfield.org : 993, implicit TLS
IMAP (STARTTLS) mail.jayfield.org : 143
SMTP submission mail.jayfield.org : 587, STARTTLS + SASL (PLAIN) auth required
Username <user>@jayfield.org (full address, not just the local part)
Password the plaintext password you hashed in §2
Port 25 not for clients — server-to-server only, no SASL, no relay (reject_unauth_destination)

disable_plaintext_auth = yes is set — clients must actually negotiate TLS first; a client configured for plaintext IMAP/SMTP on the wrong port will just fail to auth, not silently send credentials in the clear.

5. Send-only accounts (sendonly = 1)

Postfix's recipient-access.cf query rejects any inbound mail to a sendonly=1 address at RCPT TO time (450/550 before it's even accepted), while the account can still authenticate via SASL on 587 and send outbound. Use this for something like a monitoring/alerting sender address that should never actually receive replies.

6. Aliases (forward one address to another mailbox)

Aliases don't need their own mailbox or password — they're a pure redirect, resolved at RCPT TO time via aliases.cf:

sudo mysql vmail -e "INSERT INTO aliases (source_username, source_domain, destination_username, destination_domain, enabled) VALUES ('sales', 'jayfield.org', 'jens', 'jayfield.org', 1);"

This host already has postmaster/hostmaster/webmaster/wlanjens as standing aliases (RFC-required roles + a house one) — check SELECT * FROM aliases; before adding a new one to avoid duplicates.

7. Disabling / removing an account

Prefer disabling over deleting — it's reversible and doesn't touch the Maildir:

sudo mysql vmail -e "UPDATE accounts SET enabled = 0 WHERE username = 'olduser' AND domain = 'jayfield.org';"

This blocks both authentication and inbound delivery immediately (both accounts.cf and recipient-access.cf filter on enabled = true). The actual mail data stays on disk at /var/vmail/mailboxes/jayfield.org/olduser/ until you decide to remove it by hand — nothing auto-deletes it.

8. Verify a new account end-to-end

Don't trust the INSERT alone — confirm both directions actually work, same discipline as SETUP.md §7:

# IMAP auth works
doveadm auth test newuser@jayfield.org

# Watch a real inbound + outbound test the same way §7 of SETUP.md describes:
# send TO newuser@jayfield.org from an external provider, confirm in
# /var/log/mail.log:
#   dovecot: lmtp(newuser@jayfield.org)<...>: sieve: msgid=<...>: stored mail into mailbox 'INBOX'
# then send FROM the new account via a real mail client on 587, confirm:
#   postfix/submission/smtpd[...]: sasl_method=PLAIN, sasl_username=newuser@jayfield.org