Install and start Postfix as a local Mail Transfer Agent (MTA) so the host can deliver service notifications and cron
output. Validate service health, set a basic mail identity, send a test message to the local root mailbox,
and confirm the message is actually delivered.
You need a working local MTA so system-generated mail (cron output, security alerts, logrotate notices, and service notifications) does not disappear silently. This host does not need to relay mail to the internet, but it must deliver mail locally and reliably across reboots.
A local MTA is still common in hardened environments. Even without an external relay, local delivery preserves operational signal (alerts, automation output) when something goes wrong.
postfix at boot.systemctl.root.
Use the native package manager for your distro. If you are on RHEL-based systems, use dnf (not legacy
yum).
# RHEL / CentOS / Fedora
sudo dnf install -y postfix mailx
# Debian/Ubuntu
sudo apt update
sudo apt install -y postfix bsd-mailx
# Arch
sudo pacman -S postfix mailutils
Postfix provides the MTA. The mail client package provides mail so you can send and read local test mail
during validation.
Installing Postfix and mail client... Done.
sudo systemctl enable --now postfix
enable ensures it starts on boot; --now starts it immediately so you can verify state.
Created symlink .../multi-user.target.wants/postfix.service → .../postfix.service.
Job for postfix.service started successfully.
systemctl status postfix --no-pager
ss -lntp | grep -E ':(25|587)\s' || true
Confirm the unit is active and that Postfix is listening locally. Depending on defaults, you may see port 25 (SMTP) and possibly 587 (submission).
● postfix.service - Postfix Mail Transport Agent
Active: active (running)
LISTEN 0 100 127.0.0.1:25 ... master
# Set a minimal mailname (common on Debian-based systems)
echo 'example.local' | sudo tee /etc/mailname
# Set Postfix myhostname/mydomain explicitly (works everywhere)
sudo postconf -e 'myhostname=mail01.example.local'
sudo postconf -e 'mydomain=example.local'
sudo postconf -e 'myorigin=$mydomain'
sudo systemctl restart postfix
This establishes predictable sender identity for local mail. Restart Postfix so settings are applied.
postfix/postconf: updated configuration
postfix restarted.
root.
echo 'Postfix local delivery test' | mail -s 'postfix-test' root
This validates local submission into the MTA. Next you confirm the message lands in root’s mailbox.
Message accepted for delivery.
# Read root mail (interactive)
sudo mail -u root
# Check queue (should be empty for local delivery)
mailq
# Check service logs (systemd journal)
sudo journalctl -u postfix --no-pager -n 50
Your “done” signal is: message visible in the root mailbox, queue not building up, and no obvious delivery errors in logs.
# Example: mail shows a new message with subject "postfix-test"
# Example: mailq returns "Mail queue is empty"
Check mailq for stuck messages, then inspect journalctl -u postfix for local delivery errors.
Also confirm you installed a mail client package so you can read local mail.
Re-check the unit state (systemctl status postfix) and whether Postfix is configured for loopback-only binding.
If you hardened the host, confirm firewall rules and SELinux context if applicable.
Validate postconf -n output and ensure myhostname, mydomain, and myorigin
match your intended identity.
This lab is safe to leave in place if you want local system mail. If you need to revert, stop/disable the service and remove the packages using your distro’s package manager.
sudo systemctl disable --now postfix
mailq
dnf install postfix mailx: Install Postfix and a local mail client on RHEL-based systems.
apt install postfix bsd-mailx: Install Postfix and a local mail client on Debian-based systems.
pacman -S postfix mailutils: Install Postfix and a local mail client on Arch.
systemctl enable --now postfix: Enable Postfix at boot and start it immediately.
systemctl status postfix: Show Postfix unit health and current runtime state.
postconf -e 'key=value': Set Postfix configuration values non-interactively.
myhostname: Host identity used in mail headers.mydomain: Domain portion for local mail identity.myorigin: Domain appended to locally-posted mail./etc/mailname: Mail name file used on some systems (commonly Debian-based).
mail -s '<subject>' <user>: Send a local message with a subject.
mail -u <user>: Read a local user’s mailbox interactively.
mailq: Display queued messages waiting for delivery.
journalctl -u postfix: View Postfix logs from the systemd journal.
-n 50: Show the most recent 50 lines.--no-pager: Print directly to stdout.ss -lntp: List listening TCP sockets and owning processes.
-l: listening sockets-n: numeric addresses/ports-t: TCP-p: process info